package java7;

import practise.sort.SortAlgrothim.SortUtil;

import java.lang.reflect.Method;
import java.util.concurrent.*;

/**
 * Created by richard on 5/18/14.
 */
public class FolkAndJoin {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Node newNode = new Node();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        Future<Node> node =  forkJoinPool.submit(new CreateTree(4,newNode,0));
        newNode = node.get();
        Method method;
        ForkJoinPool forkJoinPool1 = new ForkJoinPool();
        Future<Integer> value =  forkJoinPool1.submit(new SumNodeInLevel(newNode,1));
        System.out.println("Sum at level :" + 2+" is :" + value.get());

    }
}

class SumNodeInLevel extends RecursiveTask<Integer>{
    private Integer level;
    private Node node;
    public SumNodeInLevel(Node node, Integer level){
        this.level = level;
        this.node = node;
    }

    @Override
    protected Integer compute() {
        if(level>0){
            SumNodeInLevel sumLeftNodeInLevel = new SumNodeInLevel(node.getLeft(),level-1);
            SumNodeInLevel sumRightNodeInLevel = new SumNodeInLevel(node.getRight(),level-1);
            sumLeftNodeInLevel.fork();
            sumRightNodeInLevel.fork();
            Integer sum = sumLeftNodeInLevel.join()+sumRightNodeInLevel.join();
            System.out.println("Detail : Sum at level :" + level+" is :" + sum);
            return sum;
        }
        else {
            System.out.println("Detail : get value :"+node.getValue()+" at level :" + level);
            return node.getValue();
        }
    }
}


class CreateTree extends RecursiveTask<Node>{
    private Integer level;
    private Node node;
    private static Integer value=1;
    private Integer innerValue;
    public CreateTree(Integer level,Node node){
        this.level = level;
        this.node = node;
    }

    public CreateTree(Integer level,Node node,Integer value){
        this.level = level;
        this.node = node;
        this.innerValue =value;
    }

    @Override
    protected Node compute() {
        if(level>1){
            CreateTree createLeft = new CreateTree(level-1,new Node(),value++);
            CreateTree createRight =  new CreateTree(level-1, new Node(),value++);

                createLeft.fork();
            node.setValue(innerValue);
                createRight.fork();
            node.setLeft(createLeft.join());
            node.setRight(createRight.join());

            System.out.println("Create Node with value:"+innerValue+"   at level:"+(5-level) );
            return node;

        }
        else{
            System.out.println("Create Node with value:"+innerValue+"   at level:"+(5-level ));
            return new Node(this.innerValue);
        }

    }
}

class Node{
    private Node left;
    private Node right;
    private Integer value;

    public Node(){

    }

    public Node(Integer value){
        this.value = value;
    }

    public Node getLeft() {
        return left;
    }

    public void setLeft(Node left) {
        this.left = left;
    }

    public Node getRight() {
        return right;
    }

    public void setRight(Node right) {
        this.right = right;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }
}
